package com.yt.user.api.client;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.yt.common.constant.Result;
import com.yt.common.enums.CodeEnum;
import com.yt.common.exception.BusinessException;
import com.yt.db.utils.RedisTokenUtil;
import com.yt.sys.models.dto.SysRoleDTO;
import com.yt.sys.models.service.ISysRoleService;
import com.yt.sys.models.service.ISysUserRoleService;
import com.yt.sys.models.vo.SysUserRoleVO;
import com.yt.user.models.bo.LoginInfoSaveBO;
import com.yt.user.models.dto.SysUserDTO;
import com.yt.user.models.service.ISysUserService;
import com.yt.user.models.vo.LoginInfoVO;
import com.yt.user.models.vo.SysUserVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.yt.user.models.service.ILoginInfoService;
import com.yt.user.models.bo.LoginInfoBO;
import com.yt.user.models.dto.LoginInfoDTO;

import java.util.HashMap;
import java.util.List;

/**
 * 登录信息控制器
 *
 * @author zhao
 * @Date 2025-09-03 16:13:38
 */

@RestController
@RequestMapping("/api/loginInfo")
@Slf4j
@Api(value = "LoginInfoApiController",tags = "登录信息Api接口")
public class LoginInfoApiController {

    @DubboReference
    private ILoginInfoService loginInfoService;
    @Autowired
    private RedisTokenUtil redisTokenUtil;


    // 注入用户角色关联服务（跨服务调用权限模块）
    @DubboReference
    private ISysUserRoleService sysUserRoleService;

    // 注入角色服务（跨服务调用权限模块，用于查询角色状态）
    @DubboReference
    private ISysRoleService sysRoleService;

    // 本地用户服务（查询用户信息）
    @DubboReference
    private ISysUserService sysUserService;

    @PostMapping("/get")
    @ApiOperation(value = "根据id查找",notes = "根据id查找")
    @ApiImplicitParam(name = "id",value = "id",required = true,paramType = "query", dataType = "Long")
    public Result<LoginInfoDTO> get(@RequestParam("id") Long id){
        if(id == null){
            return new Result<>(CodeEnum.FAIL_100002 );
        }

        LoginInfoDTO dto = loginInfoService.selectById(id);

        return new Result<>(dto);
    }

    @ApiOperation(value = "登录信息列表",notes = "登录信息列表")
    @PostMapping("/queryPageList")
    public Result<Page<LoginInfoDTO>> queryPageList(LoginInfoBO bo){
        Wrapper<LoginInfoDTO> wrapper = new EntityWrapper<>();
        if (bo.getStatus() != null){
            wrapper.eq("status", bo.getStatus());
        }
        if (bo.getStartDate() != null){
            wrapper.ge("create_time", bo.getStartDate());
        }
        if (bo.getEndDate() != null){
            wrapper.le("create_time", bo.getEndDate());

        }
        Page<LoginInfoDTO> page = new Page<>(bo.getPageNo(), bo.getPageSize());
        page = loginInfoService.selectPage(page, wrapper);

        return new Result<>(page);
    }

    @ApiOperation(value = "登录",notes = "登录")
    @PostMapping(value = "/login")
    public Result<HashMap<String,Object>> login(@RequestBody LoginInfoSaveBO loginBO) {
        HashMap<String,Object> map =  new HashMap<String,Object>();
        if(null == loginBO){
            return new Result<>(CodeEnum.FAIL_100002);
        }

        // 判断账号是否存在
        LoginInfoVO loginVO = loginInfoService.getLogin(loginBO);
        if(null == loginVO){
            return new Result<>(CodeEnum.FAIL_USER_200003);
        }

        // 校验密码并获取用户信息
        SysUserVO userInfoVO = loginInfoService.getUserLogin(loginBO);
        if(null == userInfoVO){
            return new Result<>(CodeEnum.FAIL_USER_200006);
        }

        // 校验用户状态是否正常（原逻辑无状态校验，此处补充）
        if (userInfoVO.getStatus() != 1) {
            return new Result<>(CodeEnum.FAIL_100014.getCode(), "用户已禁用，无法登录");
        }

        // 校验用户是否关联启用的管理员角色
        boolean isAdmin = checkAdminRoleWithStatus(userInfoVO.getId());
        if (!isAdmin) {
            return new Result<>(CodeEnum.FAIL_100012.getCode(), "非启用的管理员角色，禁止登录");
        }

        // 生成Token并存入Redis
        String token = redisTokenUtil.generateToken(userInfoVO.getUserName());
        userInfoVO.setToken(token);

        // 返回结果
        map.put("userInfoVO",userInfoVO);
        return new Result<>(map);
    }

    /**
     * 校验用户是否关联“启用的管理员角色”
     * 逻辑：通过用户角色关联表获取角色ID -> 查询角色详情 -> 校验角色名称和状态
     */
    private boolean checkAdminRoleWithStatus(Long userId) {
        try {
            // 跨服务调用：查询用户关联的角色列表（包含角色ID和名称）
            List<SysUserRoleVO> userRoles = sysUserRoleService.selectByUserId(userId);
            if (userRoles.isEmpty()) {
                log.warn("用户[{}]未关联任何角色", userId);
                return false;
            }

            // 遍历角色，查询角色详情并校验状态
            for (SysUserRoleVO roleVO : userRoles) {
                // 跨服务调用：查询角色详情（包含状态）
                SysRoleDTO roleDTO = sysRoleService.selectById(roleVO.getRoleId());
                if (roleDTO == null) {
                    log.warn("角色[{}]不存在", roleVO.getRoleId());
                    continue;
                }

                // 校验角色名称为“管理员”且状态为启用（1）
                if ("管理员".equals(roleDTO.getRoleName()) && roleDTO.getStatus() == 1) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            log.error("校验管理员角色失败", e);
            throw new BusinessException(CodeEnum.FAIL_100013.getCode(), "角色校验异常");
        }
    }


    @ApiOperation(value = "登录",notes = "登录")
    @PostMapping(value = "/emplogin")
    public Result<HashMap<String,Object>> uselogin(@RequestBody LoginInfoSaveBO loginBO) {
        HashMap<String,Object> map =  new HashMap<String,Object>();
        if(null == loginBO){
            return new Result<>(CodeEnum.FAIL_100002);
        }

        // 判断账号是否存在
        LoginInfoVO loginVO = loginInfoService.getLogin(loginBO);
        if(null == loginVO){
            return new Result<>(CodeEnum.FAIL_USER_200003);
        }

        // 校验密码并获取用户信息
        SysUserVO userInfoVO = loginInfoService.getUserLogin(loginBO);
        if(null == userInfoVO){
            return new Result<>(CodeEnum.FAIL_USER_200006);
        }

        // 校验用户状态是否正常
        if (userInfoVO.getStatus() != 1) {
            return new Result<>(CodeEnum.FAIL_100014.getCode(), "用户已禁用，无法登录");
        }

        // 生成Token并存入Redis
        String token = redisTokenUtil.generateToken(userInfoVO.getUserName());
        userInfoVO.setToken(token);

        // 返回结果
        map.put("userInfoVO",userInfoVO);
        return new Result<>(map);
    }
}